

public class BoardResult 
{
	//[columnIndex][rowIndex]
	//[x][y]
	//left -> right, top -> bottom
	//0 = water
	//# = ship of that length
	public char[][] populatedBoard;
	
	public int shipsOutOfBounds;
	public int shipPartsOutOfBounds;
	
	public int shipsOverlapping;
	public int shipPartsOverlapping;
    
    public int shipsAdjacent;
    public int shipPartsAdjacent;
	
	public int failingRows; //Number of rows that fail to have the target number of ship parts in that row 
	public int failingColumns; //Number of column that fail to have the target number of ship parts in that column
	
    public int shipPartsFailingRows; //Number ship parts different from actual for rows
    public int shipPartsFailingColumns; //Number ship parts different from actual for columns
    
    public int level;
    
	BoardResult(Ship[] ships, Board board, int level)
	{
		this.shipsOverlapping = 0;
		this.shipPartsOverlapping = 0;
        this.shipsAdjacent = 0;
        this.shipPartsAdjacent = 0;
		this.shipsOutOfBounds = 0;
		this.shipPartsOutOfBounds = 0;
        this.shipPartsFailingRows = 0;
        this.shipPartsFailingColumns = 0;
        
        this.level = level;
        
		this.populatedBoard = new char[board.width][board.height];
		
		for (int i=0; i<populatedBoard.length; i++)
		{
			for (int j=0; j<populatedBoard[i].length; j++)
			{
				populatedBoard[i][j] = '0';
			}
		}
		
		this.populateBoard(ships);
		this.computeFailingRows(board);
		this.computeFailingColumns(board);
	}
	
	private void populateBoard(Ship[] ships)
	{
            int j = 0;
		for (Ship ship : ships)
		{
                    if (j > level)
                        break;
                    j++;
			boolean isShipOutOfBounds = false;
			boolean isShipOverlapping = false;
                        boolean isShipAdjacent = false;
			int x = ship.locationX;
			int y = ship.locationY;
			int xModifier = 0;
			int yModifier = 0;
			
			if (ship.orientation == Ship.ORIENTATION_UP)
			{
				yModifier = -1;
			} 
			else if (ship.orientation == Ship.ORIENTATION_RIGHT)
			{
				xModifier = 1;				
			}
			else if (ship.orientation == Ship.ORIENTATION_DOWN)
			{
				yModifier = 1;				
			}
			else if (ship.orientation == Ship.ORIENTATION_LEFT)
			{
				xModifier = -1;				
			}
			else
			{
				System.out.println("ERROR: Unrecognized orientation value");
			}
			
			int shipLength = ship.getLength();
			for (int i=0; i<shipLength; i++)
			{				
				//Check for out of bounds
				if (x < 0  || x >= populatedBoard.length
					|| y < 0 || y >= populatedBoard[x].length)
				{				
					//Only count it once per ship
					if (! isShipOutOfBounds)
					{
						shipsOutOfBounds++;
						isShipOutOfBounds = true;
					}

					shipPartsOutOfBounds++;
				}
				else
				{
					//Check for overlapping ships
					if (populatedBoard[x][y] != '0')
					{
                        //Only count it once per ship
                        if (! isShipOverlapping)
                        {
                            shipsOverlapping++;
                            isShipOverlapping = true;
                        }

                        shipPartsOverlapping++;
					}
                    
                    //Check for adjacent ships
                    if (i == 0) //First part of ship
                    {
                        if (ship.orientation == Ship.ORIENTATION_UP)
                        {
                            if (x > 0 && y < populatedBoard.length - 1
                                    && populatedBoard[x - 1][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (y < populatedBoard.length - 1
                                    && populatedBoard[x][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (x < populatedBoard.length - 1 && y < populatedBoard.length - 1
                                    && populatedBoard[x + 1][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                        }
                        else if (ship.orientation == Ship.ORIENTATION_RIGHT)
                        {
                            if (x > 0 && y > 0
                                    && populatedBoard[x - 1][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (x > 0
                                    && populatedBoard[x - 1][y] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if(x > 0 && y < populatedBoard.length - 1
                                    && populatedBoard[x - 1][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                        }
                        else if (ship.orientation == Ship.ORIENTATION_DOWN)
                        {
                            if (x > 0 && y > 0
                                    && populatedBoard[x - 1][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (y > 0
                                    && populatedBoard[x][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (x < populatedBoard.length - 1 && y > 0
                                    && populatedBoard[x + 1][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                        }
                        else if (ship.orientation == Ship.ORIENTATION_LEFT)
                        {
                            if (x < populatedBoard.length - 1 && y > 0
                                    && populatedBoard[x + 1][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (x < populatedBoard.length - 1
                                    && populatedBoard[x + 1][y] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if(x < populatedBoard.length - 1 && y < populatedBoard.length - 1
                                    && populatedBoard[x + 1][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                        }
                    }
                    
                    if (i == shipLength-1) //Last part of ship
                    {
                        if (ship.orientation == Ship.ORIENTATION_UP)
                        {
                            if (x > 0 && y > 0
                                    && populatedBoard[x - 1][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (y > 0
                                    && populatedBoard[x][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (x < populatedBoard.length - 1 && y > 0
                                    && populatedBoard[x + 1][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                        }
                        else if (ship.orientation == Ship.ORIENTATION_RIGHT)
                        {
                            if (x < populatedBoard.length - 1 && y > 0
                                    && populatedBoard[x + 1][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (x < populatedBoard.length - 1
                                    && populatedBoard[x + 1][y] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if(x < populatedBoard.length - 1 && y < populatedBoard.length - 1
                                    && populatedBoard[x + 1][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                        }
                        else if (ship.orientation == Ship.ORIENTATION_DOWN)
                        {
                            if (x > 0 && y < populatedBoard.length - 1
                                    && populatedBoard[x - 1][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (y < populatedBoard.length - 1
                                    && populatedBoard[x][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (x < populatedBoard.length - 1 && y < populatedBoard.length - 1
                                    && populatedBoard[x + 1][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                        }
                        else if (ship.orientation == Ship.ORIENTATION_LEFT)
                        {
                            if (x > 0 && y > 0
                                    && populatedBoard[x - 1][y - 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if (x > 0
                                    && populatedBoard[x - 1][y] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                            if(x > 0 && y < populatedBoard.length - 1
                                    && populatedBoard[x - 1][y + 1] != '0') {
                                isShipAdjacent = true;
                                shipPartsAdjacent++;
                            }
                        }
                    }
                    
                    if (ship.orientation == Ship.ORIENTATION_UP || ship.orientation == Ship.ORIENTATION_DOWN)
                    {
                        if (x > 0 && populatedBoard[x-1][y] != '0')
                        {
                            isShipAdjacent = true;
                            shipPartsAdjacent++;
                        }
                        
                        if (x < populatedBoard.length-1 && populatedBoard[x+1][y] != '0')
                        {
                            isShipAdjacent = true;
                            shipPartsAdjacent++;
                        }
                    }
                    else if (ship.orientation == Ship.ORIENTATION_LEFT || ship.orientation == Ship.ORIENTATION_RIGHT)
                    {
                        if (y > 0 && populatedBoard[x][y-1] != '0')
                        {
                            isShipAdjacent = true;
                            shipPartsAdjacent++;
                        }
                        
                        if (y < populatedBoard.length-1 && populatedBoard[x][y+1] != '0')
                        {
                            isShipAdjacent = true;
                            shipPartsAdjacent++;
                        }
                    }
					
					populatedBoard[x][y] = (char)('0' + shipLength);
				}
				
				x += xModifier;
				y += yModifier;
			}
            
            if (isShipAdjacent)
                shipsAdjacent++;
		}
	}
	
	private void computeFailingRows(Board board)
	{
		this.failingRows = 0;
		
		//[columnIndex][rowIndex]
		//[x][y]
		//left -> right, top -> bottom
		
		for (int i=0; i<populatedBoard[0].length; i++)
		{
			int shipPartCount = 0;
			
			for (int j=0; j<populatedBoard.length; j++)
			{
				if (populatedBoard[j][i] != '0')
				{
					shipPartCount++;
				}
			}
			
			if (shipPartCount != board.rowTargetList.get(i))
			{
				this.failingRows++;
                this.shipPartsFailingRows += Math.abs(shipPartCount - board.rowTargetList.get(i));
			}
		}
	}
	
	private void computeFailingColumns(Board board)
	{
		this.failingColumns = 0;
		
		for (int i=0; i<populatedBoard.length; i++)
		{
			int shipPartCount = 0;
			
			for (int j=0; j<populatedBoard[i].length; j++)
			{
				if (populatedBoard[i][j] != '0')
				{
					shipPartCount++;
				}
			}
			
			if (shipPartCount != board.columnTargetList.get(i))
			{
				this.failingColumns++;
                this.shipPartsFailingColumns += Math.abs(shipPartCount - board.columnTargetList.get(i));
			}
		}
	}
	
	public String getPrintedBoard()
	{
		String ret = "";
		
        int columnCount = 0;
        int rowCount = 0;
        
        //print column count
		for (int i=0; i<populatedBoard.length; i++)
		{
            columnCount = 0;
            
			for (int j=0; j<populatedBoard[i].length; j++)
			{
                if (populatedBoard[i][j] != '0')
                    columnCount++;
			}
            ret += columnCount;
		}
        ret += "\n\n";
        
		for (int i=0; i<populatedBoard.length; i++)
		{
            rowCount = 0;
            
			for (int j=0; j<populatedBoard[i].length; j++)
			{
                if (populatedBoard[j][i] != '0')
                    rowCount++;
                
				ret += populatedBoard[j][i];
			}
            ret += "  " + rowCount;
			ret += "\n";
		}
		
		return ret;
	}
}
